//! @Author: DengLibin 榆霖
//! @Date:  2022-07-07 16:18:50
//! @Description: 文章 接口

use std::{cell::RefCell, collections::HashMap};

use actix_web::{
    get,
    http::{header::ContentType, Error},
    post,
    web::{self, Data},
    HttpResponse, Scope,
};

use common::pojo::ResData;
use dao::{entity::article::Article, pojo::DbParam};
use service::article_service;

/// @Author: DengLibin 榆霖
/// @Date:  2022-04-21 11:33:&01
/// @Description: 路由配置
pub fn route() -> Scope {
    info!("article_controller配置路由");
    let sys_scope = web::scope("/article");
    sys_scope.service(get_page).service(insert).service(view)
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-07 16:23:38
/// @Description: 分页查询
#[get("/get_page")]
async fn get_page(
    mysql_conn_pool: Data<mysql::Pool>, //连接池，全局参数传过来
    query: web::Query<HashMap<String, String>>, //查询参数
) -> HttpResponse {
    //获取查询参数
    let page_str = query.get("page").unwrap();
    let size_str = query.get("size").unwrap();
    let page: i32 = page_str.parse().unwrap();
    let size: i32 = size_str.parse().unwrap();
    //获取连接池
    let p = (*(mysql_conn_pool)).clone();
    //查询参数
    let db_param = DbParam {
        page: page,
        size: size,
        pool: p,
    };
    let p = article_service::get_page(&db_param).unwrap();

    HttpResponse::Ok().json(ResData::success(p)) // <- send response
}

/// @Author: DengLibin 榆霖
/// @Date:  2022-07-06 11:17:13
/// @Description: 添加
#[post("/insert")]
async fn insert(
    id_generator: Data<RefCell<common::utils::IdGenerator>>, //id生成器
    mysql_conn_pool: Data<mysql::Pool>,                      //连接池，全局参数传过来
    article: web::Json<Article>,
) -> HttpResponse {
    //获取连接池
    let p = (*(mysql_conn_pool)).clone();
    let generator = id_generator;
    let mut a = article.to_owned();
    a.id = generator.borrow_mut().next_id();
    let param = dao::pojo::ArticleParam {
        article: a,
        pool: p,
    };
    let r = article_service::insert(&param);
    let result = match r {
        Ok(b) => ResData {
            code: 0,
            msg: "success",
            data: b,
        },
        Err(e) => {
            error!("添加失败:{}", e);
            ResData::fail("fail", false)
        }
    };
    HttpResponse::Ok().json(result) // <- send response
}

#[get("/{id}")]
pub async fn view(
    mysql_conn_pool: Data<mysql::Pool>,
    id: web::Path<i64>,
) -> Result<HttpResponse, Error> {
    let i = id.to_owned();
    //获取连接池
    let p = (*(mysql_conn_pool)).clone();
    let ao = article_service::get_by_id(i, &p);

    if let Some(a) = ao {
        let r = article_service::get_all(&p).unwrap();

        let conent = format_page(a, r);

        return Ok(HttpResponse::Ok()
            .content_type(ContentType::html())
            .body(conent));
    }

    Ok(HttpResponse::NotFound()
        .content_type(ContentType::plaintext())
        .body("资源不存在"))
}

fn format_page(article: Article, articles: Vec<Article>) -> String {
    let mut conent = String::new();

    let s1 = format!(
        r#"
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="keywords" content="{}" />
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>{}</title>
      <script src="/static/jquery3.6.0.js"></script>
      <link href="/static/css/common.css" rel="stylesheet" />
      <link href="/static/layui/css/layui.css" rel="stylesheet" />
      <link href="/static/css/index.css" rel="stylesheet" />
      <link href="/static/css/github-markdown.css" rel="stylesheet" />
    
      <!-- 引入 layui.js -->
      <script src="/static/layui/layui.js"></script>
    </head>
    
    <body style="width: 1200px; margin: 0 auto;">
      <div class="layui-header header header-demo" autumn="" id="title">我的学习笔记
      </div>
      <div class="main">
        <div class="content">{}</div>
        <ul class="layui-nav layui-nav-tree layui-inline" lay-filter="demo" style="margin-right: 10px; height: 100%;">
    "#,
    article.title, article.title, markdown::to_html(article.content.as_str())
    );

    conent.push_str(s1.as_str());
    let mut open_class = String::new();
    for a in articles.iter() {
        
        if a.parent_id == 0 {
            open_class.clear();
            if article.parent_id == a.id {
                open_class.push_str("layui-nav-itemed");
            } 

            let li = format!(
                r#"<li class="layui-nav-item {}">
                    <a href="javascript:;">{}</a>"#,
                    open_class, a.title
            );

            conent.push_str(li.as_str());

            let dl = create_dl(article.id, a.id, &articles);
            println!("{}", &dl);
            conent.push_str(dl.as_str());

            conent.push_str(r#"</li>"#);
        }
    }
    conent.push_str(r#" </ul>
        </div>
    </body>
</html>"#);
    return conent;
}

fn create_dl(article_id: i64, parent_id: i64, articles: &Vec<Article>) -> String {
    let mut dl = String::new();
    dl.push_str(r#" <dl class="layui-nav-child">"#);

    let mut class_this = String::new();
    for a in articles {
        class_this.clear();
        if a.parent_id == parent_id {
            if a.id == article_id {
                class_this.push_str("layui-this");
            }

            dl.push_str(
                format!(r#"<dd class="{}"><a href="/article/{}">{}</a></dd>"#, class_this, a.id, a.title).as_str(),
            );
        }
    }
    dl.push_str(r#" </dl>"#);

    return dl;
}
